home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Language/OS - Multiplatform Resource Library
/
LANGUAGE OS.iso
/
pcr
/
pcr4_4.lha
/
DIST
/
threads
/
Threads2.c
< prev
next >
Wrap
C/C++ Source or Header
|
1991-01-10
|
8KB
|
347 lines
/* begincopyright
Copyright (c) 1988 Xerox Corporation. All rights reserved.
Use and copying of this software and preparation of derivative works based
upon this software are permitted. Any distribution of this software or
derivative works must comply with all applicable United States export
control laws. This software is made available AS IS, and Xerox Corporation
makes no warranty about the software, its performance or its conformity to
any specification. Any person obtaining a copy of this software is requested
to send their name and post office or electronic mail address to:
PCR Coordinator
Xerox PARC
3333 Coyote Hill Rd.
Palo Alto, CA 94304
endcopyright */
/*
* Threads2.c
*
* Demers, January 10, 1991 1:16:42 pm PST
*/
#include "xr/BasicTypes.h"
#include "xr/Errno.h"
#include "xr/Threads.h"
#include "xr/ThreadsBackdoor.h"
#include "xr/ThreadsPrivate.h"
#include "xr/ThreadsSignalsPrivate.h"
#include "xr/ThreadsMsgPrivate.h"
void
XR_GetCurrent (result)
struct XR_CTRep *result;
{
result->ct_thread = XR_currThread;
result->ct_gen = XR_currThread->t_gen;
}
void
XR_Yield ()
{
XR_Switch(NIL, XR_SSTAT_READY, XR_SWSTAT_THREAD);
}
int
XR_PauseAbortable (ticks)
XR_Ticks ticks;
{
XR_CV cv;
if( ticks == 0 ) return( XR_AbortPending() ? -1 : 0 );
cv = &(XR_currThread->t_timerCV);
XR_EnableAborts( cv );
XR_SetTimeout( cv, ticks );
return( XR_WaitCV(cv, NIL) );
}
void
XR_PauseNotAbortable(ticks)
XR_Ticks ticks;
{
XR_CV cv;
if( ticks == 0 ) return;
cv = &(XR_currThread->t_timerCV);
XR_DisableAborts( cv );
XR_SetTimeout( cv, ticks );
(void)XR_WaitCV(cv, NIL);
}
int
XR_CancelAbort (ct)
XR_CT ct;
{
XR_Thread t;
if( ct == NIL ) {
t = XR_currThread;
} else {
if( (t = ct->ct_thread) == NIL ) return(-1);
if( t->t_gen != ct->ct_gen ) return(-1);
}
t->t_abortRequest = FALSE;
return(0);
}
/*
* ??? this may be too conservative about holding the MetaLock ???
*/
int
XR_AbortCT (ct)
XR_CT ct;
{
XR_Thread t = ct->ct_thread;
XR_Thread each = XR_currThread;
XR_WQ wq;
bool doSetReady = FALSE;
if( t == NIL ) return(-1);
XR_MonitorEntry(&(t->t_ml));
if( t->t_gen != ct->ct_gen ) {
XR_MonitorExit(&(t->t_ml));
return(-1);
}
t->t_abortRequest = TRUE;
XR_LockMeta("AbortCT 0");
for(;;) {
if( !(t->t_abortRequest) /* process has seen abort request */
) {
break;
}
if( (t->t_sStat != XR_SSTAT_WAIT_CV) /* already woke up */
|| (!(t->t_abortable)) /* not abortable */
|| ((wq = t->t_wq) == NIL) /* in notify or timeout */
) {
break;
}
if( XR_TryGSL(&(wq->wq_gsl)) /* got the wait queue */ ) {
if( t->t_wq == wq /* ... and not in notify or timeout */ ) {
XR_RemWQ(t);
doSetReady = TRUE;
break; /* XR_ReleaseGSL happens below */
}
XR_ReleaseGSL(&(wq->wq_gsl));
} else {
/* can't acquire the wait queue, so do a directed */
/* yield to somebody who might hold it ... */
XR_Thread limit = &(XR_sysArea->sa_threadPool[XR_maxThreads]);
XR_Thread holder = NIL;
int i;
XR_UnlockMeta();
for( i = 0; i < XR_maxThreads; i++ ) {
if( ++each >= limit ) each = &(XR_sysArea->sa_threadPool[0]);
if( each->t_wq == wq ) { holder = each; break; }
}
XR_Switch(holder, XR_SSTAT_READY, XR_SWSTAT_THREAD);
XR_LockMeta("AbortCT 1");
}
}
XR_UnlockMeta();
XR_MonitorExit(&(t->t_ml));
if( doSetReady ) {
XR_VPE best = XR_SetThreadReady(t);
XR_ReleaseGSL(&(wq->wq_gsl));
if( best == XR_vpe ) {
XR_Switch(t, XR_SSTAT_READY, XR_SWSTAT_THREAD);
} else if( best != NIL ) {
XR_RequestResched(best);
}
}
XR_CheckReschedRequest();
return(0);
}
int
XR_ValidateCT (ct)
XR_CT ct;
{
XR_Thread t = ct->ct_thread;
if( (t == NIL) || (t->t_gen != ct->ct_gen) )
return(-1);
return(0);
}
/*
* Per-thread client data
*
* The initializations support the OBSOLETE threadProperty stuff ...
*/
static struct XR_MLRep
XR_threadDataRegistrationsLock = XR_NULL_ML_REP;
typedef struct XR_ThreadDataRegistrationRep {
XR_Pointer tdr_key;
bool tdr_inherited;
} *XR_ThreadDataRegistration;
static struct XR_ThreadDataRegistrationRep
XR_threadDataRegistrations[XR_NUM_PER_THREAD_DATA] = {
{ 1, FALSE }, /* t_property */
{ 2, TRUE }, /* t_inheritedProperty */
{ 0, FALSE }
};
int
XR_GetPerThreadDataID(key, create, inherit)
XR_Pointer key;
bool create;
bool inherit;
{
int i, ans;
if( XR_currThread == NIL ) {
XR_Panic("GetPerThreadDataID 0");
}
if( key == 0 ) {
XR_SetErrno(EINVAL);
return (-1);
}
XR_MonitorEntry(&XR_threadDataRegistrationsLock);
for( i = 0; ; i++ ) {
if( i >= XR_NUM_PER_THREAD_DATA ) {
ans = (-1); XR_SetErrno(ENOMEM);
goto Out;
}
if( XR_threadDataRegistrations[i].tdr_key == NIL ) {
if( create ) {
XR_threadDataRegistrations[i].tdr_key = key;
XR_threadDataRegistrations[i].tdr_inherited = inherit;
ans = ((int)(&(XR_currThread->t_perThreadData[i])))
- ((int)(XR_currThread));
} else {
ans = (-1); XR_SetErrno(EINVAL);
}
goto Out;
}
if( XR_threadDataRegistrations[i].tdr_key == key ) {
if( create ) {
ans = (-1); XR_SetErrno(EINVAL);
} else {
ans = ((int)(&(XR_currThread->t_perThreadData[i])))
- ((int)(XR_currThread));
}
goto Out;
}
}
Out:
XR_MonitorExit(&XR_threadDataRegistrationsLock);
return ans;
}
void
XR_InheritPerThreadData(from, to)
XR_Thread from;
XR_Thread to;
{
XR_ThreadDataRegistration reg;
XR_Pointer *pTo;
int i;
reg = XR_threadDataRegistrations;
pTo = to->t_perThreadData;
for( i = 0; i < XR_NUM_PER_THREAD_DATA; i++ ) {
if( reg->tdr_inherited ) {
*pTo++ = from->t_perThreadData[i];
} else {
*pTo++ = NIL;
}
reg++;
}
}
/* OBSOLETE */
int
XR_GetPerThreadDataOffset(key, create)
XR_Pointer key;
bool create;
{
return XR_GetPerThreadDataID(key, create, FALSE);
}
XR_Pointer *
XR_GetPerThreadDataSlot(byteOffset)
int byteOffset;
{
return XR_GetPerThreadDataAddress(byteOffset);
}
XR_Pointer
XR_GetThreadProperty ()
{
return( XR_currThread->t_perThreadData[0] );
}
XR_Pointer
XR_GetThreadInheritedProperty ()
{
return( XR_currThread->t_perThreadData[1] );
}
void
XR_SetThreadProperty (p)
XR_Pointer p;
{
XR_currThread->t_perThreadData[0] = p;
}
void
XR_SetThreadInheritedProperty (p)
XR_Pointer p;
{
XR_currThread->t_perThreadData[1] = p;
}
void
XR_SetPriority (pri)
XR_Pri pri;
/*
Set priority of current thread.
If priority increases, this won't be reflected in XR_vpe->vpe_pri
until the next thread switch, but that's benign.
Note you're not allowed to set priority to XR_PRI_SYS_EXCLUSIVE
using this (obsolescent) interface -- see ThreadsSchedCtl.h.
*/
{
if( pri > XR_PRI_LAST ) {
pri = XR_PRI_LAST;
} else if( pri <= XR_PRI_IDLE ) {
pri = XR_PRI_IDLE;
}
if( (pri == XR_PRI_IDLE)
&& (XR_currThread->t_index >= XR_sysArea->sa_numVP) ) {
pri += 1;
}
if( pri == XR_PRI_SYS_EXCLUSIVE ) {
pri -= 1;
}
XR_currThread->t_pri = pri;
XR_Yield();
}